<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        /**
         *  object.defineProperty()
         * 有数据描述符和存取描述符 这两者不能共同存在
         * 
         * **/


        // 数据描述符
        // 
        /**数据描述符和存取描述符共同拥有的可选键值为
         * configurable  默认值false
         * 当该键值为true的时候。该属性的描述符才能被改变，同时也能从对应的对象上被删除
         * enumerable 默认值false
         * 当该键值为true 时，该属性才会出现对象的枚举属性中
         * 
         * 
         * 数据描述符还具有以下的可选键值
         * value 默认值undefined
         * 该属性对应的值，可以是任何有效的JavaScript值
         * writable 默认值false
         * 当该属性为true 时，属性的值，也就是上面的value 才能被改变
         * 
         * 
         * 存取描述符还具有以下的可选键值
         * get 默认undefined
         * 属性的getter函数，如果没有getter，则为undefined。当访问该属性时，会调用此函数
         * 执行时不传入任何参数，但是会传入this对象(由于继承关系，这里的this并不一定是定义该属性的对象)
         * 该函数的返回值会被用作属性的值
         * 
         * 
         * set 默认undefined
         * 属性的setter函数，如果没有setter，则为undefined。当属性被修改时，会调用此函数。
         * 该方法接受一个参数(也就是被赋予的新值)，会传入赋值时的this 对象
         * 
         * **/

        let obj = {}
        // 这里时数据描述符
        // writable 属性 能否被修改
        Object.defineProperty(obj, 'a', {
            value: 1,
            // writable:false, //当此键值为false 时不能修改value 值
            writable: true //当此键值为true时可以修改value 值
        })
        obj.a = 2
        console.log(obj);

        // enumerable 属性  能否被遍历
        let obj1 = {}
        Object.defineProperty(obj1, 'a', { value: 'a', enumerable: true })
        Object.defineProperty(obj1, 'b', { value: 'b', enumerable: false })
        Object.defineProperty(obj1, 'c', { value: 'c' })
        obj1.d = 'd'
        // Symbol.for(key) 方法会根据给定的键 key，来从运行时的 symbol 注册表中找到对应的 symbol，如果找到了，则返回它，否则，新建一个与该键关联的 symbol，并放入全局 symbol 注册表中。
        Object.defineProperty(obj1, Symbol.for('e'), {
            value: 5,
            enumerable: true
        });

        for (const key in obj1) {
            console.log(key, 'forin');
        }

        console.log(Object.keys(obj1));


        // configurable  可否能删除
        let obj2 = {}

        // Object.defineProperty(obj2, 'a', {
        //     get() {
        //         return 1
        //     },
        //     configurable: false
        // })
        Object.defineProperty(obj2, "a", {
            configurable: true,
        });

        console.log(obj2.a);
        delete obj2.a;
        console.log(obj2.a);

        // get 和set
        function Archiver() {
            var temperature = null;
            var archive = [];
            Object.defineProperty(this, 'temperature', {
                get: function () {
                    console.log('get!');
                    return temperature;
                },
                set: function (value) {
                    temperature = value;
                    archive.push({ val: temperature });
                }
            });
            this.getArchive = function () { return archive };
        }
        var arc = new Archiver();
        arc.temperature;
        arc.temperature = 11;
        arc.temperature = 13;
        console.log(arc.getArchive());


        let PerSon={}
        let temp=null
        Object.defineProperty(PerSon,'name',{
            get(){
                return temp
            },
            set(newValue){
                console.log(newValue,'newValue');
                temp=newValue
            }
        })
        PerSon.name='jack'
        console.log(PerSon.name,'set',temp);


        // 循环使用同一对象

        let obj3={}
        let obj4={}
        function withValue(value) {
            var d = withValue.d || (
                withValue.d = {
                    enumerable: false,
                    writable: false,
                    configurable: false,
                    value: null
                }
            );
            d.value = value;
            return d;
        }
        // ... 并且 ...
        Object.defineProperty(obj3, "key", withValue("static"));
        Object.defineProperty(obj4, "key", withValue("as "));
        console.log(obj4);
        console.log(obj3);

    </script>
</body>

</html>